package com.tj.pystandard.tjgateway.filter;

import com.tj.pystandard.tjgateway.constant.SystemConstant;
import com.tj.pystandard.tjgateway.vo.ResponseVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

@Slf4j
@Component
public class TokenFilter implements GlobalFilter, Ordered {


    @Override
    public int getOrder() {
        return 20;
    }

    public static Map<String,String> userTokenInfo = new HashMap<>();

    static {
        userTokenInfo.put("1","tangjing");
        userTokenInfo.put("123456789tokenStr","jack");
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String requestPath = request.getPath().toString();
        // 无需拦截接口
        boolean noNeedFilter = SystemConstant.NO_NEED_FILTER.stream().anyMatch( requestPath::contains );
        if (noNeedFilter) {
            request = exchange.getRequest().mutate()
                    //.header( SystemConstant.ACCESS_IP, Objects.requireNonNull( exchange.getAttribute( SystemConstant.ACCESS_IP ) ).toString() )
                    //.header( SystemConstant.LOG_ID, Objects.requireNonNull( exchange.getAttribute( SystemConstant.LOG_ID ) ).toString() )
                    .build();
            ServerWebExchange buildExchange = exchange.mutate().request( request ).build();
            return chain.filter( buildExchange );
        }
        // 1.获取token
        String token = getToken( request );
        // 2.校验token
        // 参数token为空
        if (StringUtils.isEmpty( token )) {
            return writeAuthResponse( response, ResponseVo.STATUS_CODE.LOGIN_WITHOUT );
        }
        // 模拟数据库通过token查询用户相关信息
        String tokenToUser = findUser(token);
        // 3.token 错误
        if (null == tokenToUser) {
            return writeAuthResponse( response, ResponseVo.STATUS_CODE.LOGIN_TOKEN_ERROR );
        }
        // 将userId放入header
        Consumer<HttpHeaders> httpHeaders = httpHeader -> {
            httpHeader.set(SystemConstant.USER_ID, tokenToUser);
        };
        request = exchange.getRequest().mutate().headers(httpHeaders).build();
        // 4.token 状态判断，其它端登录，todo异地登录等
        //ResponseVo.STATUS_CODE statusCode = loginStatusCheck( tokenInfo );
        ServerWebExchange buildExchange = exchange.mutate().request( request ).build();
        return chain.filter( buildExchange );
    }

    /**
     * 获取用户token
     *
     * @param request 请求
     * @return token
     */
    private String getToken(ServerHttpRequest request) {
        String token = request.getQueryParams().getFirst( SystemConstant.TOKEN );
        if (StringUtils.isEmpty( token )) {
            token = request.getHeaders().getFirst( SystemConstant.TOKEN );
        }
        return token;
    }

    /**
     * 返回权限验证结果
     *
     * @param response   res
     * @param authStatus 权限状态
     * @return Mono
     */
    private Mono<Void> writeAuthResponse(ServerHttpResponse response, ResponseVo.STATUS_CODE authStatus) {
        ResponseVo<String> responseVo = new ResponseVo<>();
        responseVo.error( authStatus );
        byte[] bits = responseVo.toString().getBytes( StandardCharsets.UTF_8 );
        DataBuffer buffer = response.bufferFactory().wrap( bits );
        response.getHeaders().add( "Content-Type", "application/json;charset=utf-8" );
        return response.writeWith( Mono.just( buffer ) );
    }

    /**
     * 模拟数据库查询token信息
     *
     * @param token
     * @return
     */
    private String findUser(String token){
        return userTokenInfo.getOrDefault(token,null);
    }
}
